#include "server.h"

server::server() {
  // http_conn类对象
  users = new http_conn[MAX_FD];

  // root文件夹路径
  char serverPath[200];
  getcwd(serverPath, 200);
  char webRoot[5] = "/web";
  strcat(serverPath, webRoot);
  chdir(serverPath);

  // 线程池
  m_pool = new threadpoll<http_conn>;
  std::cout << "server init ok..." << std::endl;
}

server::~server() {

  close(m_epollFd);
  close(m_listenFd);

  delete[] users;
  delete m_pool;
}

void server::init() {}

void server::eventListen() { //创建监听socket 挂载到epoll红黑树
  m_listenFd = socket(AF_INET, SOCK_STREAM, 0);
  if (m_listenFd == -1)
    printError("listenFd socket() error...");
  struct sockaddr_in serverAddr;
  bzero(&serverAddr, sizeof(serverAddr));
  serverAddr.sin_family = AF_INET;
  serverAddr.sin_addr.s_addr = INADDR_ANY;
  serverAddr.sin_port = htons(PORT);
  socklen_t serverAddrLen = sizeof(serverAddr);
  // 设置优雅关闭
  struct linger temp = {1, 0};
  setsockopt(m_listenFd, SOL_SOCKET, SO_LINGER, &temp, sizeof(temp));
  int ret = bind(m_listenFd, (sockaddr *)&serverAddr, serverAddrLen);
  if (ret == -1)
    printError("listenFd bind() error...");
  ret = listen(m_listenFd, 20);
  if (ret == -1)
    printError("listenFd listen() error...");

  m_epollFd = epoll_create(5);
  //挂载到epoll红黑树；
  addFdOnEpollTree(m_epollFd, m_listenFd, false);
  http_conn::epollFd = m_epollFd;
}

void server::eventLoop() {
  bool serverStop = false;
  while (!serverStop) {
    int number = epoll_wait(m_epollFd, events, MAX_EVENT_NUMBER, -1);
    if ((number < 0) && (errno != EINTR)) {
      std::cout << "epoll failure" << std::endl;
      break;
    }
    for (int i = 0; i < number; ++i) {
      int curActiveFd = events[i].data.fd;
      if (curActiveFd == m_listenFd) { // 新客户连接
        struct sockaddr_in clientAddr;
        socklen_t clientAddrLen = sizeof(clientAddr);
        int connFd =
            accept(m_listenFd, (sockaddr *)&clientAddr, &clientAddrLen);
        if (connFd < 0) {
          perror("connfd < 0...");
          continue;
        }
        if (http_conn::myUserCnt >= MAX_FD) {
          show_error(connFd, "server busy");
          continue;
        }
        users[connFd].init(connFd, clientAddr);
      } else if (events[i].events & (EPOLLHUP | EPOLLRDHUP | EPOLLERR)) {
        users[curActiveFd].closeConn();
      } else if (events[i].events & EPOLLIN) { // 读事件
        if (users[curActiveFd].read()) {
          m_pool->append(users + curActiveFd);
        } else {
          users[curActiveFd].closeConn();
        }
      } else if (events[i].events & EPOLLOUT) { // 写事件
        if (!users[curActiveFd].write()) {
          users[curActiveFd].closeConn();
        }
      }
    }
  }
}
